﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.Threading;
using System.Windows.Markup;

namespace DiscoveryLogic.UI.Layouts.Controls
{
    public partial class PageTurn : UserControl
    {
        #region Private Variables

            private int maxNumPages;
            private NavigationManager navigationManager;
            private List<PageTurnPage> pages;

        #endregion

        #region Constructors

        /// <summary>
            /// Create new instance of the PageTurn obj
            /// </summary>
            /// <param name="maxNumPages"></param>
            /// <param name="pageTurnPages"></param>
            public PageTurn(int maxNumPages, List<PageTurnPage> pageTurnPages)
            {
                InitializeComponent();

                this.maxNumPages = maxNumPages;

                // create NavigationManager
                this.navigationManager = new NavigationManager(this.Root, this.maxNumPages);

                // Based on the list of pageTurnPages (front), create the back of those pages
                AddOddPages();
                // Add the list of pages
                AddEvenPages(pageTurnPages);

                this.Loaded += new RoutedEventHandler(PageTurn_Loaded);
                navigationManager.PageChanged += new EventHandler(OnPageChanged);
            }

        #endregion

        #region Private Methods

            /// <summary>
            /// On page flipped
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            void OnPageChanged(object sender, EventArgs e)
            {
                bool monthChanged = true;

                if (MonthChanged != null && monthChanged)
                {
                    MonthChanged(this, e);
                }
            }
            
            /// <summary>
            /// When page turn has loaded, show the fold on the 
            /// bottom right of the page
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            void PageTurn_Loaded(object sender, EventArgs e)
            {
                //Storyboard sb = (Storyboard)control.FindName("SlideIn");
                //sb.Completed += new EventHandler(sb_Completed);
                //sb.Begin();
                sb_Completed(null, null); 
            }

            /// <summary>
            /// Show the page fold on the bottom right of the page
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            void sb_Completed(object sender, EventArgs e)
            {
                this.navigationManager.BeginPageAnimation("showFold");
            }

        #endregion Private Methods

        #region Public Properties

            /// <summary>
            /// Returns the navigation manager
            /// </summary>
            public NavigationManager NavigationManager
            {
                get
                {
                    return navigationManager;
                }
            }            

            /// <summary>
            /// Returns the list of pages (front)
            /// </summary>
            public List<PageTurnPage> Pages
            {
                get
                {
                    return pages;
                }
            }

            /// <summary>
            /// Get the abbreviation of the previous month
            /// </summary>
            /// <returns></returns>
            public string GetPreviousMonth()
            {
                try
                {
                    int nextOddPage = navigationManager.NextOddPage;
                    PageTurnPage curr = pages[nextOddPage / 2];

                    for (int search = 1; search < pages.Count; search++)
                    {
                        if (nextOddPage / 2 - search < 0 || nextOddPage / 2 - search >= pages.Count)
                        {
                            return "";
                        }

                        PageTurnPage ptp = pages[nextOddPage / 2 - search];
                        if (!ptp.Statement.Abbreviation.Equals(curr.Statement.Abbreviation))
                        {
                            return ptp.Statement.Abbreviation;
                        }
                    }
                }
                catch  
                {
                }

                return "";
            }


            /// <summary>
            /// Get abbreviation of the next month
            /// </summary>
            /// <returns></returns>
            public string GetNextMonth()
            {
                try
                {
                    int nextOddPage = navigationManager.NextOddPage;
                    PageTurnPage curr = pages[nextOddPage / 2];

                    for (int search = 1; search < pages.Count; search++)
                    {
                        if (nextOddPage / 2 + search < 0 || nextOddPage / 2 + search >= pages.Count)
                        {
                            return "";
                        }

                        PageTurnPage ptp = pages[nextOddPage / 2 + search];
                        if (!ptp.Statement.Abbreviation.Equals(curr.Statement.Abbreviation))
                        {
                            return ptp.Statement.Abbreviation;
                        }
                    }
                }
                catch 
                {
                }

                return "";
            }

            /// <summary>
            /// Prepends a zero to a single digit number or returns
            /// the integer if a double digit number is passed in
            /// </summary>
            /// <param name="number"></param>
            /// <returns></returns>
            public string GetTwoDigitInt(int number)
            {
                // if this number already has two digits, return the int part
                if ((number < 0) || (number >= 10))
                {
                    return Math.Floor(number).ToString();
                }

                // otherwise, prepend zero
                return "0" + Math.Floor(number);
            }

            /// <summary>
            /// Creates the xaml for the back page Adds odd pages to the Page Turn
            /// </summary>
            public void AddOddPages()
            {

                // if maxNumPages is odd, we will ignore the last page, so last odd is two behind
                int _lastOdd;
                if (((this.maxNumPages / 2) - Math.Floor(this.maxNumPages / 2)) == 0)
                {
                    _lastOdd = this.maxNumPages - 1;
                }
                else
                {
                    _lastOdd = this.maxNumPages - 2;
                }

                // Create odd pages
                for (int i = 1; i <= _lastOdd; i = i + 2)
                {
                    try
                    {

                        // this is the template for all odd pages
                        string oddStr = String.Format("<Canvas x:Name='page0{0}' xmlns='http://schemas.microsoft.com/client/2007' xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>", GetTwoDigitInt(i));
                        oddStr = oddStr + String.Format("  <Canvas.RenderTransform>");
                        oddStr = oddStr + String.Format("    <TransformGroup>");
                        oddStr = oddStr + String.Format("      <RotateTransform x:Name='page{0}Rotate' CenterX='0' CenterY='430' Angle='0'/>", GetTwoDigitInt(i));
                        oddStr = oddStr + String.Format("      <TranslateTransform x:Name='page{0}Translate' X='0' Y='0'/>", GetTwoDigitInt(i));
                        oddStr = oddStr + String.Format("    </TransformGroup>");
                        oddStr = oddStr + String.Format("  </Canvas.RenderTransform>");

                        string contents = String.Format("<Canvas Name='PagableStatement{0}'/>", GetTwoDigitInt(i));
                        oddStr += contents;

                        oddStr = oddStr + String.Format("  <Canvas.Clip>");
                        oddStr = oddStr + String.Format("    <PathGeometry>");
                        oddStr = oddStr + String.Format("      <PathFigure>");
                        oddStr = oddStr + String.Format("        <LineSegment Point='0,430'/>");
                        oddStr = oddStr + String.Format("        <LineSegment x:Name='page{0}Point1' Point='0, 430'/>", GetTwoDigitInt(i));
                        oddStr = oddStr + String.Format("        <LineSegment x:Name='page{0}Point2' Point='0, 430'/>", GetTwoDigitInt(i));
                        oddStr = oddStr + String.Format("        <LineSegment x:Name='page{0}Point3' Point='0, 430'/>", GetTwoDigitInt(i));
                        oddStr = oddStr + String.Format("        <LineSegment Point='0,430'/>");
                        oddStr = oddStr + String.Format("      </PathFigure>");
                        oddStr = oddStr + String.Format("    </PathGeometry>");
                        oddStr = oddStr + String.Format("  </Canvas.Clip>");
                        oddStr = oddStr + String.Format("  <Rectangle Height='1000' Width='20' Opacity='0.1' x:Name='page{0}FoldShadow'>", GetTwoDigitInt(i));
                        oddStr = oddStr + String.Format("    <Rectangle.RenderTransform>");
                        oddStr = oddStr + String.Format("      <TransformGroup>");
                        oddStr = oddStr + String.Format("        <RotateTransform x:Name='page{0}FoldShadowRotate' CenterX='0' CenterY='0' Angle='0'/>", GetTwoDigitInt(i));
                        oddStr = oddStr + String.Format("        <TranslateTransform x:Name='page{0}FoldShadowTranslate' X='0' Y='0'/>", GetTwoDigitInt(i));
                        oddStr = oddStr + String.Format("      </TransformGroup>");
                        oddStr = oddStr + String.Format("    </Rectangle.RenderTransform>");
                        oddStr = oddStr + String.Format("    <Rectangle.Fill>");
                        oddStr = oddStr + String.Format("      <LinearGradientBrush StartPoint='0,0' EndPoint='1,0'>");
                        oddStr = oddStr + String.Format("        <GradientStop Color='#00000000' Offset='0'/>");
                        oddStr = oddStr + String.Format("        <GradientStop Color='#FF000000' Offset='1'/>");
                        oddStr = oddStr + String.Format("      </LinearGradientBrush>");
                        oddStr = oddStr + String.Format("    </Rectangle.Fill>");
                        oddStr = oddStr + String.Format("  </Rectangle>");
                        oddStr = oddStr + String.Format("</Canvas>");

                        Canvas newOddPage = XamlLoader<Canvas>.Create(oddStr);

                        Canvas pagableStatementCanvas = (Canvas)newOddPage.FindName(String.Format("PagableStatement{0}", GetTwoDigitInt(i)));

                        // Create new page (back)
                        PageTurnPageBack ptpb = new PageTurnPageBack();

                        // Add it to the canvas
                        pagableStatementCanvas.Children.Add(ptpb);

                        // Hook up event handlers to allow user to turn the page back
                        newOddPage.MouseLeftButtonDown += new MouseButtonEventHandler(this.navigationManager.OddPageMouseDown);
                        newOddPage.MouseLeftButtonUp += new MouseButtonEventHandler(this.navigationManager.OddPageMouseUp);
                        newOddPage.MouseMove += new MouseEventHandler(this.navigationManager.OddPageMouseMove);

                        oddPageCanvas.Children.Add(newOddPage);
                    }
                    catch 
                    {
                    }
                }
            }

            /// <summary>
            /// Create the xaml for the page (front) and add it to the PageTurn canvas
            /// </summary>
            /// <param name="pages"></param>
            public void AddEvenPages(List<PageTurnPage> pages)
            {
                this.pages = pages;

                // Determine the last even page
                int _lastEven;
                if (((this.maxNumPages / 2) - Math.Floor(this.maxNumPages / 2)) == 0)
                {
                    _lastEven = this.maxNumPages;
                }
                else
                {
                    _lastEven = this.maxNumPages - 1;
                }

                // For each even page, add xaml for the page
                for (int i = _lastEven; i >= 0; i = i - 2)
                {

                    string foldShadowStr = String.Format("  <Rectangle Height='430' Width='30' Opacity='1.'>");
                    foldShadowStr += String.Format("    <Rectangle.Fill>");
                    foldShadowStr += String.Format("      <LinearGradientBrush StartPoint='0,0' EndPoint='1,0'>");
                    foldShadowStr += String.Format("        <GradientStop Color='#BBFFFFFF' Offset='0'/>");
                    foldShadowStr += String.Format("        <GradientStop Color='#00FFFFFF' Offset='1'/>");
                    foldShadowStr += String.Format("      </LinearGradientBrush>");
                    foldShadowStr += String.Format("    </Rectangle.Fill>");
                    foldShadowStr += String.Format("  </Rectangle>");

                    //this is the template for all even pages
                    string evenStr = String.Format("<Canvas x:Name='page0{0}' xmlns='http://schemas.microsoft.com/client/2007' xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>", GetTwoDigitInt(i));
                    evenStr = evenStr + String.Format("  <Canvas.Clip>");
                    evenStr = evenStr + String.Format("    <PathGeometry>");
                    evenStr = evenStr + String.Format("      <PathFigure>");
                    evenStr = evenStr + String.Format("        <LineSegment Point='0, 0'/>");
                    evenStr = evenStr + String.Format("        <LineSegment Point='0, 430'/>");
                    evenStr = evenStr + String.Format("        <LineSegment x:Name='page{0}Point1' Point='340, 430'/>", GetTwoDigitInt(i));
                    evenStr = evenStr + String.Format("        <LineSegment x:Name='page{0}Point2' Point='340, 430'/>", GetTwoDigitInt(i));
                    evenStr = evenStr + String.Format("        <LineSegment x:Name='page{0}Point3' Point='340, 0'/>", GetTwoDigitInt(i));
                    evenStr = evenStr + String.Format("        <LineSegment Point='0, 0'/>");
                    evenStr = evenStr + String.Format("      </PathFigure>");
                    evenStr = evenStr + String.Format("    </PathGeometry>");
                    evenStr = evenStr + String.Format("  </Canvas.Clip>");

                    if (i != 0)
                    {
                        evenStr = evenStr + foldShadowStr;
                    }

                    string contents = String.Format("<Canvas Name='PagableStatement{0}'/>", GetTwoDigitInt(i));

                    evenStr += contents;

                    evenStr = evenStr + String.Format("</Canvas>");

                    Canvas c = DiscoveryLogic.UI.Layouts.XamlLoader<Canvas>.Create(evenStr);

                    Canvas pagableStatementCanvas = (Canvas)c.FindName(String.Format("PagableStatement{0}", GetTwoDigitInt(i)));
                    //PageTurnPage ps = new PageTurnPage();

                    PageTurnPage ps = pages[i / 2];

                    ps.PageIndex = i;

                    pagableStatementCanvas.Children.Add(ps);

                    // Add the even page xaml to the canvas
                    evenPageCanvas.Children.Add(c);
                }
            }

        #endregion Public Properties

        #region Events

            // Event that is raised when page is flipped
            public event EventHandler MonthChanged;

        #endregion
    }
}
